/*
 * server.h
 *
 *  Created on: Oct 22, 2009
 *      Author: thienlong
 */
#ifndef SERVER_H_
#define SERVER_H_

#include <sys/socket.h>
#include <netinet/in.h>
#include <event2/event.h>
#include <event2/http.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include "config.h"
#include "../lib/credis.h"
#include "server.h"
#include "socket_item.h"
#include "reuse-data.h"
#include "server-status.h"

#undef FD_SETSIZE
#define FD_SETSIZE 200000

#ifndef FREE_SIZE
#define FREE_SIZE 64
#endif

#ifdef HAVE_SERVER_STATUS
#define STATUS_URI "/status"
#define INTERVAL_PARAM "interval"
#endif

#define REDIS_TIMEOUT 10000
/* item in the socket queue */

struct thread_state {
	pthread_t thread_id;
	struct event_base *base; 				/* libevent handler this thread uses */
	struct evhttp *http; 						/* http event base */
	struct event *notify_event; 			/* listen event for notify pipe */
	int notify_receive_fd; 					/* receiving end of notify pipe */
	int notify_send_fd; 					/* sending end of notify pipe */
	struct socket_queue connect_sockets; 	/* queue of new connections for handle */
	linked_pool cache;						/* cache for fetching data*/
};

extern void settings_init();
extern void worker_thread_init(ServerConf *conf);
extern void dispatch_connection(struct socket_item *sck, struct thread_state *thread);
extern struct thread_state* thread_get_request_handler(int nthreads);
/* declare functions which perform with socket_queue */
extern void socket_queue_init(struct socket_queue *queue);
extern struct socket_item *socket_queue_peek(struct socket_queue *queue);
extern struct socket_item *socket_queue_pop(struct socket_queue *queue);
extern void socket_queue_push(struct socket_queue *queue,
		struct socket_item *item);
/*free all data entry which a given queue links to. It free itself too*/
extern void socket_queue_free(struct socket_queue *queue);
extern void socket_queue_clear(linked_pool *cache, struct socket_queue *queue);
extern void socket_queue_free_item(struct socket_queue *queue);
extern int socket_queue_size(struct socket_queue *queue);
/* declare functions which perform on cache */
extern struct socket_item *socket_item_new();
extern void socket_item_free(struct socket_item *item);
/* define event handler call back */
typedef void (*event_handler)(int fd, short event_flags, void *arg);
extern int update_event(int fd, struct event *notify_event,
		struct event_base *base, short event_flags, event_handler handler,
		void *arg);
extern void do_accept(int listener, short event_flags, void *args);
extern void server_handler_default(struct evhttp_request *req, void *args);
extern void server_status(struct evhttp_request * req, void *args);
/* setup server */
extern int server_init(int port, int pendNum);
/* declare functions which perform on server_status */
extern void server_status_init(struct server_status *status);
extern void server_status_increase_conn(struct server_status *status);
extern void server_status_increase_req(struct server_status *status);
extern long server_status_get_conn(struct server_status *status);
extern long server_status_get_req(struct server_status *status);
extern time_t server_status_get_starttime(struct server_status *status);
val load_content_file(key k, mem_storage *storage, void *arg);
#endif /* SERVER_H_ */
